package HuffmanTree;
import Structure.List;
import Structure.SinglyLinkedList;
import java.util.Scanner;
//EJEMPLO DE INGRESO: AAAAAAAAAABBBBBBBBCCCCCCCDDDDEE

/**
 * Huffman2.java        
 * Fecha: 21/09/12
 * Carnet: 11033
 * Modificado Por: Juan Pablo Argueta Cortés
 * NOTA: Tomado de los ejemplos del Libro Java Structure de Duane A. Bailey
 * 
 * Clase que permite ingresar una cadena, la cual es codificada utilizando el
 * algoritmo de Huffman. Luego muestra al usuario la codificación realizada.
 * El programa permite decodificar un código a partir de la codificación realizada.
 *
 * @version $Id: BinaryTree.java 34 2007-08-09 14:43:44Z bailey $
 * @author, 2001 duane a. bailey
 */
public class Huffman2
{
    /**
     *
     * @param args
     */
    public static void main(String args[])
    {
        List<node> freq = new SinglyLinkedList<node>();
        Scanner teclado = new Scanner(System.in);
        System.out.println("Ingrese la cadena a codificar:");
        String cadena = teclado.nextLine();
        // read data from input
        for (int i=0; i<cadena.length(); i++)
        {
            char c = cadena.charAt(i);
            // look up character in frequency list
            node query = new node(c);
            node item = freq.remove(query);
            if (item == null)
            {   // not found, add new node
                freq.addFirst(query);
            } else { // found, increment node
                item.incFrecuency();
                freq.addFirst(item);
            }
        }
        // insert each character into a huffman tree
        VectorHeap<huffmanTree> trees = new VectorHeap<huffmanTree>();
        for (node n : freq)
        {
            trees.add(new huffmanTree(n));
        }

        // merge trees in pairs until one remains
        while (trees.size() > 1)
        {
            // grab two smallest values
            huffmanTree smallest = (huffmanTree)trees.remove();
            huffmanTree small = (huffmanTree)trees.remove();
            // add bigger tree containing both
            trees.add(new huffmanTree(smallest,small));
        }
        System.out.println("\nEl proceso de codificación ha terminado.\nLa codificación es la siguiente:\n");
        huffmanTree codificacion = trees.remove();
        codificacion.print();
        
        String entrada;
        int opcion = 0;
        do{
            boolean invalido;
            do{ 
                System.out.println("\n¿Desea decodificar algún mensaje?");
                System.out.println("1.)Sí\n2.)No\n");
                entrada = teclado.next();
                try{
                    opcion = Integer.parseInt(entrada);
                    invalido = false;
                    if ((opcion!=1)&&(opcion!=2)){
                        System.out.println("\nEsa no es una opción válida. Vuelva a intentarlo.");
                        invalido = true;
                    }
                }catch(Exception e){
                    System.out.println("\nEsa no es una opción válida. Vuelva a intentarlo.");
                    invalido = true;
                }
            }while(invalido);
            
            if (opcion==1){
                String codigo, mensaje = "";
                do{ 
                    System.out.println("\nIngrese el código a decodifiar:");
                    try{
                        codigo = teclado.next();
                        mensaje = codificacion.decode(codigo);
                        invalido = false;
                    }catch(Exception e){
                        System.out.println("\nEse no es un código válido. Vuelva a intentarlo.");
                        invalido = true;
                    }
                }while(invalido);
                System.out.println("\nEl mensaje decodificado es: " + mensaje);  
            } else {
                System.out.println("\nHasta Luego!");
            }
        }while(opcion==1);
    }
}

